package net.wicp.tams.common.binlog.self.replication;

import java.io.IOException;

import net.wicp.tams.common.Result;
import net.wicp.tams.common.apiext.ByteUtil;

public abstract class AbsPacketWrite implements IPacketWrite {

	private static final long serialVersionUID = 1L;

	protected int buffSize = 1000;
	protected int sequence = 1;

	@Override
	public final byte[] writeBody() throws IOException {
		Result checkRet = check();
		if (!checkRet.isSuc()) {
			throw new IllegalArgumentException(checkRet.getMessage());
		}
		//PacketBean packetBean = PacketBean.builder().build();
		ByteUtil.AssitWrite assitori = new ByteUtil.AssitWrite(buffSize);
		packPacket(assitori);
		byte[] data = assitori.get();
		//packetBean.setBody(new LogBuffer(data, 0, data.length));
		//packetBean.setSequence(sequence);

		ByteUtil.AssitWrite assit = new ByteUtil.AssitWrite(
				data.length + 4 * (data.length / MAX_PACKET_LENGTH + 1));
		if (data.length< MAX_PACKET_LENGTH) { // Single packet
			assit.write(data.length, 3);
			assit.write(sequence, 1);
			assit.write(data);
			// assit.write(packetBean.getBody().getData());
		} else {
			// If the length of the packet is greater than the value of
			// MAX_PACKET_LENGTH,
			// which is defined to be power(2, 24) �C 1 in sql/net_serv.cc, the
			// packet gets
			// split into smaller packets with bodies of MAX_PACKET_LENGTH plus
			// the
			// last
			// packet with a body that is shorter than MAX_PACKET_LENGTH.
			byte[][] muliBody = ByteUtil.splitBytes(data, MAX_PACKET_LENGTH);
			for (int i = 0; i < muliBody.length; i++) {
				assit.write(MAX_PACKET_LENGTH, 3);
				assit.write(sequence++, 1);
				assit.write(muliBody[i]);
			}
			// The last short packet will always be present even if it must have
			// a
			// zero-length body.
			// It serves as an indicator that there are no more packet parts
			// left in
			// the stream for this large packet.
			assit.write(0, 3);
			assit.write(sequence++, 1);
			assit.write(new byte[0]);
		}
		return assit.get();

	}

	public abstract void packPacket(ByteUtil.AssitWrite assit);

	protected abstract Result check();

}
